Skip to content

feat: #2228 Add tool origin tracking to ToolCallItem and ToolCallOutputItem#2242

Draft
habema wants to merge 13 commits intoopenai:mainfrom
habema:feat/track-tool-origin
Draft

feat: #2228 Add tool origin tracking to ToolCallItem and ToolCallOutputItem#2242
habema wants to merge 13 commits intoopenai:mainfrom
habema:feat/track-tool-origin

Conversation

@habema
Copy link
Contributor

@habema habema commented Dec 28, 2025

Adds tool_origin field to ToolCallItem and ToolCallOutputItem to track where function tools came from (regular functions, MCP servers, or agent-as-tool). This helps with debugging and tracing which MCP server handled a call when using multiple servers.

The tool_origin is a ToolOrigin object that contains:

  • type: The origin type (FUNCTION, MCP, or AGENT_AS_TOOL)
  • mcp_server_name: The MCP server name (only set for MCP tools)
  • agent_as_tool_name: The agent name (only set for agent-as-tool)

New tests added

Closes #2228

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

habema added a commit to habema/openai-agents-python that referenced this pull request Dec 28, 2025
Copy link
Member

@seratch seratch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our current top priority is to merge HITL enhancement, which changes runner internals a lot. So, we may ask you to resolve the conflicts after the big PR is merged.


return run_result.final_output

# Set origin tracking on the FunctionTool created by @function_tool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems the code comment here is incorrect

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to Set origin tracking on run_agent (the FunctionTool returned by @function_tool) for more clarity

mcp_server_name: str | None = None
"""The name of the MCP server. Only set when type is MCP."""

agent_as_tool_name: str | None = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This object may receive feature requests to have more properties, so simply having the reference to the agent object may be fine. Same for mcp_server_name too

Copy link
Contributor Author

@habema habema Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I've changed the implementation so that the objects are stored. I'm not too sure about the custom __repr__, below is an example of what ToolOrigin would look like with and without it. Let me know what you think.


Without a __repr__ method, ToolOrigin would look like:

  • MCP
    ToolOrigin(type=<ToolOriginType.MCP: 'mcp'>, mcp_server=<tests.mcp.helpers.FakeMCPServer object at 0x...>, agent_as_tool=None)
  • Agent as tool:
    ToolOrigin(type=<ToolOriginType.AGENT_AS_TOOL: 'agent_as_tool'>, mcp_server=None, agent_as_tool=Agent(name='test_agent', handoff_description=None, tools=[], mcp_servers=[], mcp_config={}, instructions='Test agent', prompt=None, handoffs=[], model=<tests.fake_model.FakeModel object at 0x...>, model_settings=ModelSettings(...), input_guardrails=[], output_guardrails=[], output_type=None, hooks=None, tool_use_behavior='run_llm_again', reset_tool_choice=True))
  • Function:
    ToolOrigin(type=<ToolOriginType.FUNCTION: 'function'>, mcp_server=None, agent_as_tool=None)

With the custom __repr__:

  • ToolOrigin(type='mcp', mcp_server_name='test_server')
  • ToolOrigin(type='agent_as_tool', agent_as_tool_name='test_agent')
  • ToolOrigin(type='function')

@seratch seratch added this to the 0.7.x milestone Jan 6, 2026
@seratch
Copy link
Member

seratch commented Jan 22, 2026

@codex review

@seratch seratch modified the milestones: 0.7.x, 0.8.x Jan 22, 2026
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8b2d12a8b0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- Add ToolOriginType enum and ToolOrigin dataclass
- Add _tool_origin field to FunctionTool
- Set tool_origin for MCP tools and agent-as-tool
- Extract and set tool_origin in ToolCallItem and ToolCallOutputItem creation
- Add comprehensive tests for tool origin tracking
@habema habema force-pushed the feat/track-tool-origin branch from 8cbf13f to edbec4e Compare February 5, 2026 12:23
@habema habema marked this pull request as ready for review February 5, 2026 12:35
@seratch seratch modified the milestones: 0.9.x, 0.10.x Feb 13, 2026
@seratch seratch removed this from the 0.10.x milestone Feb 26, 2026
@habema
Copy link
Contributor Author

habema commented Mar 1, 2026

@codex review please

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8776b02295

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@habema
Copy link
Contributor Author

habema commented Mar 1, 2026

@codex review a final time please

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e96186113b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@habema
Copy link
Contributor Author

habema commented Mar 1, 2026

@codex review please

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. 🎉

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@seratch
Copy link
Member

seratch commented Mar 1, 2026

Thanks for working on this. I did a few additional codex reviews and it pointed the following things out. Also, I feel this change requires a minor version bump, so we won't immediately merge it.

  1. On src/agents/run_state.py#L696

tool_origin for agent.as_tool() is serialized/deserialized by agent name only. Agent.name is not unique, so this breaks as soon as an orchestrator has two nested agents with the same name. I reproduced this locally with two different dup agents: after RunState.to_json()/from_json(), the restored tool_origin.agent_as_tool pointed to the first one in the map, not the one that actually handled the tool call. That makes the persisted provenance incorrect.

  1. On src/agents/run_internal/tool_execution.py#L875

The new provenance is preserved for rejected/executed tool results, but not for the pending approval path. When needs_approval=True and approval_status is None, we create a ToolApprovalItem without tool_origin, so callers still cannot tell whether the pending tool came from a local function tool, MCP tool, or agent.as_tool(). If we want tool_origin to be a reliable provenance signal, it needs to be attached to approval interruptions as well.

@seratch seratch marked this pull request as draft March 1, 2026 22:45
1. **Agent-as-tool identity** – Switched from `agent.name` to `agent_index` in serialization so duplicate agent names are handled correctly.
2. **`_build_agent_map`** – Now returns `(agent_map, agent_list)` with `id()`-based visited tracking.
3. **`ToolApprovalItem`** – Added `tool_origin` and `release_agent` for provenance on pending approvals.
4. **RunState** – Added `_starting_agent` and optional `root_agent` for correct agent graph traversal during serialization.
@habema
Copy link
Contributor Author

habema commented Mar 1, 2026

@seratch I understand that the scale of changes here requires a minor bump, no worries. I've addressed your comments, let me know if there are any others.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable to access MCP server name via its converted function tool object

2 participants